package com.zzb.framework.common.minimalist;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.List;

import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zzb.framework.common.BasePage;
import com.zzb.framework.common.BaseResponse;
import com.zzb.framework.common.FrameworkException;
import com.zzb.framework.common.PageSearchForm;
import com.zzb.framework.query.GenericQueryDAO;

public class MinimalistBaseService<M extends BaseMapper<T>, T extends MinimalistEntity> extends ServiceImpl<M, T> {
	@Autowired
	private GenericQueryDAO genericQueryDAO;

	public Class<T> getClazz() {
		return (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[1];
	}

	/**
	 * 通过用户id获取实体
	 */
	public <PK extends Serializable> T get(PK id) {
		return getById(id);
	}

	/**
	 * 物理删除
	 */
	public <PK extends Serializable> BaseResponse deleteById(PK id) {
		boolean b = super.removeById(id);
		if (b) {
			return new BaseResponse<>(BaseResponse.SUCCESS, "删除成功");
		} else {
			return new BaseResponse<>(BaseResponse.FAIL, "删除失败");
		}
	}

	@Transactional
	public <PK extends Serializable> BaseResponse deleteByIds(List<PK> ids) {
		if (CollectionUtils.isEmpty(ids))
			throw new FrameworkException("删除失败，记录不存在");
		boolean b = removeByIds(ids);
		if (b) {
			return new BaseResponse<>(BaseResponse.SUCCESS, "删除成功");
		} else {
			return new BaseResponse<>(BaseResponse.FAIL, "删除失败");
		}
	}

	/**
	 * 保存或更新
	 */

	public BaseResponse<T> insertOrUpdate(T record) {
		if (record == null)
			throw new FrameworkException("保存失败，记录不能为空");
		if (record.getId() != null && exists(record.getId())) {
			return update(record);
		} else {
			return insert(record);
		}
	}

	public BaseResponse<List<T>> insertOrUpdateList(List<T> records) {
		if (CollectionUtils.isEmpty(records))
			throw new FrameworkException("保存失败，记录不能为空");
		records.forEach(this::insertOrUpdate);
		return new BaseResponse<>(BaseResponse.SUCCESS, "保存成功", records);
	}

	/**
	 * 插入，如果存在相同id抛异常
	 */

	public BaseResponse<T> insert(T record) {
		if (record == null)
			throw new FrameworkException("保存失败，记录不能为空");
		if (save(record)) {
			return new BaseResponse<>(BaseResponse.SUCCESS, "保存成功", record);
		} else {
			return new BaseResponse<>(BaseResponse.FAIL, "保存失败", record);
		}
	}

	public BaseResponse<List<T>> insertList(List<T> records) {
		if (CollectionUtils.isEmpty(records))
			throw new FrameworkException("保存失败，记录不能为空");
		if (saveBatch(records)) {
			return new BaseResponse<>(BaseResponse.SUCCESS, "保存成功", records);
		} else {
			return new BaseResponse<>(BaseResponse.FAIL, "保存失败", records);
		}
	}

	/**
	 * 更新，如果数据库中没有记录，则抛异常
	 */

	public BaseResponse<T> update(T record) {
		if (record == null)
			throw new FrameworkException("更新失败，记录不能为空");
		if (updateById(record)) {
			return new BaseResponse<>(BaseResponse.SUCCESS, "更新成功", record);
		} else {
			return new BaseResponse<>(BaseResponse.FAIL, "更新失败", record);
		}
	}

	public BaseResponse<List<T>> updateList(List<T> records) {
		if (CollectionUtils.isEmpty(records))
			throw new FrameworkException("更新失败，记录不能为空");
		if (updateBatchById(records)) {
			return new BaseResponse<>(BaseResponse.SUCCESS, "更新成功", records);
		} else {
			return new BaseResponse<>(BaseResponse.FAIL, "更新失败", records);
		}
	}

	/**
	 * 查找所有实体列表
	 *
	 * @return 返回实体列表
	 */
	public List<T> selectAll() {
		return super.list();
	}

	public <PK extends Serializable> List<T> selectByIds(List<PK> ids) {
		return (List<T>) super.listByIds(ids);
	}

	/**
	 * 查找所有记录数
	 *
	 * @return 返回实体记录数
	 */
	public int countAll() {
		return super.count();
	}

	/**
	 * 查询是否存在记录
	 */
	public <PK extends Serializable> boolean exists(PK id) {
		return getById(id) != null;
	}

	/**
	 * 搜索分页
	 * StringMatcher 选项如下
	 * CONTAINING ->   LOWER(column) like '%' + LOWER(?) + '%'
	 * DEFAULT -> column = ?
	 * INSENSITIVE -> LOWER(column) = LOWER(?)
	 * 可自定义StringMatcher
	 */
	public <S extends PageSearchForm> BasePage<T> queryPage(S searchForm) {
		return genericQueryDAO.queryPage(searchForm, getClazz());
	}
}
